home *** CD-ROM | disk | FTP | other *** search
- /* LAP802.c contains the IEEE 802.3 LAP interface code for IP
-
- (c) Copyright 1990-91 by Apple Computer, Inc. All rights reserved.
-
- */
-
- /*
- 1.2 Oct 1990 Rajesh modified for IEEE 802.3 LAP.
- 1.0d2 11/25/87 JEM Changes for CITI-like interface
- 1.0d1 9/14/87 JEM Initial rewrite for "attachPH" interface to Enet driver
- */
-
- #define __ALLNU__ /* allow MAC II ROM functions */
-
- #include <Devices.h>
- #include <Errors.h>
- #include <Events.h>
- #include <Memory.h>
- #include <Traps.h>
- #include <Retrace.h>
- #include <Resources.h>
- #include <ROMDefs.h>
- #include <Slots.h>
- #include <AppleTalk.h>
-
- #include "MacTCPCommonTypes.h"
- #include "MiscIPPB.h"
- #include "LAPMisc.h"
- #include "LAP802.h"
-
- #define SlotManage 0xA06E /* slot manager trap */
- #define UnimplTrap 0xA89F /* unimplemented trap trap */
-
- #define spCategoryMask 0x08 /* mask off catagory field */
- #define spCTypeMask 0x04 /* mask off type field */
- #define spDrvrSWMask 0x02 /* mask off driver software field */
- #define spDrvrHWMask 0x01 /* mask off driver hardware field */
-
- /* definitions of LAP handler routines */
- extern OSErr Lap802_init(struct Lap802Info *lap);
- extern OSErr Lap802_open(struct Lap802Info *lap);
- extern OSErr Lap802_attachPH(struct Lap802Info *lap, ProcPtr ptr);
- extern OSErr Lap802_detachPH(struct Lap802Info *lap);
- extern void Lap802_read_ph();
- extern void Lap802p3_ph();
- extern void Lap802_readE_ph();
- extern OSErr Lap802_write(struct Lap802Info *lap, ip_addr dest, struct ipbuf *ipb);
- extern OSErr Lap802_control(struct Lap802Info *lap);
- extern void Lap802_fault(struct Lap802Info *lap);
- extern OSErr Lap802_statistics(tempLap, statsPtr);
- extern Boolean Lap802_register(struct Lap802Info *lap);
- extern Boolean Lap802_probe(struct Lap802Info *lap, ip_addr addr);
- extern OSErr Lap802_close(struct Lap802Info *lap);
-
- extern void TLoopBack(struct wdsEntry *wds);
- extern long L802Attach(ProcPtr prot_handler, long ioRefNum, char *protType);
- extern long L802Detach(long ioRefNum, char *protType);
- extern Ptr A5Swap(Ptr oldA5);
- extern void bzero(char *ptr, int len);
- extern void IOComplete(struct ipbuf *ipb);
- extern Ptr GetA0(void);
- extern Ptr GetA5(void);
-
-
- /* other IEEE 802.3 internal routines */
- void Lap802_writecomplete(void);
- void config_RARP(struct Lap802Info *lap);
- void SendRARP (struct Lap802Info *lap, int arp_code);
-
- struct Lap802Info *Lap802_main()
- {
- struct Lap802Info *lap;
-
- lap = (struct Lap802Info *) NewPtr(sizeof(struct Lap802Info));
- if (lap != nil) {
- bzero((Ptr)lap, sizeof(struct Lap802Info));
-
- lap->lapInit = Lap802_init;
- lap->lapOpen = Lap802_open;
- lap->lapClose = Lap802_close;
- lap->lapUnload = nil;
- lap->lapAttach = Lap802_attachPH;
- lap->lapDetach = Lap802_detachPH;
- lap->lapOutput = Lap802_write;
- lap->lapControl = Lap802_control;
- lap->lapFault = del_arp_entry;
- lap->lapRegister = Lap802_register;
- lap->lapProbe = Lap802_probe;
- lap->lapConfigure = config_RARP;
- lap->lapStatistics = Lap802_statistics;
- lap->lapFindGateway = nil;
- lap->lapGwyCheck = nil;
- lap->headerSize = sizeof(struct Lap802_header);
- lap->outMaxPacketSize = MAX_LAP802_PKT;
- lap->inMaxPacketSize = MAX_LAP802_PKT;
- lap->maxDataSize = MAX_LAP802_PKT - sizeof(struct Lap802_header);
-
- lap->lapType = ARP_ETHERNET;
- lap->lapAddrLength = sizeof(struct Lap802_addr);
- lap->lapAddrPtr = (Ptr) &lap->our_lap_addr;
-
- lap->lap_broadcast_addr.lap_hi= 0xFFFF;
- lap->lap_broadcast_addr.lap_lo = 0xFFFFFFFF;
-
- lap->ipGlobals = GetA5();
- lap->addressConflict = false;
-
- SetLAPPtr(lap);
- }
- return(lap);
- }
-
-
- OSErr Lap802_init(lap, disconnectProc)
- struct Lap802Info *lap;
- ProcPtr disconnectProc;
- {
- OSErr rc = -1;
- struct Lap802PB lappb;
- struct SpBlock sb;
- struct SlotDevParam xpb;
- char driver_name[8];
- char prot_IP[] = {HEX_1,HEX_AA,HEX_5,HEX_0,HEX_0,HEX_0,HEX_8,HEX_0,HEX_0};
- char prot_ARP[] = {HEX_1,HEX_AA,HEX_5,HEX_0,HEX_0,HEX_0,HEX_8,HEX_6,HEX_0};
-
- lap->ip_ph = nil;
-
- /* open .ENET driver */
- driver_name[0] = '\005';
- driver_name[1] = '.';
- driver_name[2] = 'E';
- driver_name[3] = 'N';
- driver_name[4] = 'E';
- driver_name[5] = 'T';
-
- bzero((char *)&xpb, sizeof(xpb));
- xpb.ioNamePtr = (StringPtr)&driver_name[0];
-
- if (NGetTrapAddress(SlotManage,OSTrap) !=
- NGetTrapAddress(UnimplTrap,OSTrap)) {
- /* running on a system with a slot manager (Mac II)
- determine which slot Ethernet card is in */
-
- /* search through Nu-bus for the first networking card */
- bzero((char *)&sb, sizeof(sb));
- sb.spSlot = lap->lc.slot;
- sb.spCategory = catNetwork;
- sb.spCType = typeEtherNet;
- sb.spTBMask = spDrvrSWMask | spDrvrHWMask;
- rc = SNextTypeSRsrc(&sb);
-
- if ((lap->lc.slot != 0) && (sb.spSlot != lap->lc.slot)) {
- /* slot of network card as set by Control Panel, isn't valid */
- rc = smEmptySlot;
- }
-
- if (rc == noErr) {
- xpb.ioSlot = sb.spSlot;
- xpb.ioID = sb.spID;
- // Debugger(); /* RAJESH MAY 22, 1991 */
- rc = OpenSlot((ParmBlkPtr)&xpb, false);
- lap->link_unit = xpb.ioRefNum;
- }
- };
- if (rc != noErr) {
- /* running on older system, just try opening driver */
- driver_name[0] = '\006';
- driver_name[6] = '0';
- rc = PBOpen((ParmBlkPtr)&xpb, false);
- lap->link_unit = xpb.ioRefNum;
- };
-
- if (rc == noErr) {
- /* get our Ethernet address from board */
- bzero((char *)&lappb, sizeof(lappb));
- lappb.ioRefNum = lap->link_unit;
- lappb.csCode = TGetInfo;
- lappb.csParam.TGetInfoPB.bufSize = sizeof(lap->our_lap_addr);
- lappb.csParam.TGetInfoPB.infoPtr = (char *)&lap->our_lap_addr;
- rc = PBControl((ParmBlkPtr)&lappb, false);
- }
-
- if (rc == noErr) {
- /* set general mode for large IP IEEE 802.3 packets */
- lappb.csCode = TSetGeneral;
- rc = PBControl((ParmBlkPtr)&lappb, false);
- }
-
- if (rc == noErr) {
- /* attach ethernet-IP protocol read handler to the ethernet driver */
- lappb.csCode = TAttachPH;
- lappb.csParam.TAttachPB.protocolType = LAP_IP;
- lappb.csParam.TAttachPB.PHaddress = (ProcPtr) Lap802_readE_ph;
- rc = PBControl((ParmBlkPtr)&lappb, false);
- }
-
- if (rc == noErr) { /* attach 802.3-IP packet read handler to LAP manager */
- rc = L802Attach((ProcPtr) Lap802p3_ph, (long) lap->link_unit, prot_IP);
- }
-
- if (rc == noErr) {
- /* attach ethernet-ARP protocol read handler to the ethernet driver */
- lappb.csCode = TAttachPH;
- lappb.csParam.TAttachPB.protocolType = LAP_ARP;
- lappb.csParam.TAttachPB.PHaddress = (ProcPtr) Lap802_readE_ph;
- rc = PBControl((ParmBlkPtr)&lappb, false);
- }
-
- if (rc == noErr) { /* attach 802.3-ARP packet read handler to LAP manager */
- rc = L802Attach((ProcPtr) Lap802p3_ph, (long) lap->link_unit, prot_ARP);
- }
-
- if (rc == noErr) {
- /* finally, IEEE 802.3 needs the services of ARP. So start it now. */
- rc = Arp_init(lap);
- }
- return(rc);
- }
-
-
- OSErr Lap802_open(lap)
- struct Lap802Info *lap;
- {
- #pragma unused (lap)
- return(noErr);
- }
-
-
- /* Lap802_attachPH is called by IP to specify the address of the IP packet
- received routine */
-
- OSErr Lap802_attachPH(lap, ptr)
- struct Lap802Info *lap;
- voidProcPtr ptr;
- {
- lap->ip_ph = ptr;
- return(noErr);
- }
-
-
- /* Lap802_detachPH is called by IP to release its packet receive routine */
-
- OSErr Lap802_detachPH(lap)
- struct Lap802Info *lap;
- {
- lap->ip_ph = nil;
- return(noErr);
- }
-
- /* Lap802_read_ph is called by the Ethernet driver when a packet is received */
-
- void Lap802_read_ph() /* reads IEEE 802.3 packets */
- {
- struct rdStruct rds;
- struct Lap802_header *lap_hdr;
- struct Lap802Info *lap;
- Ptr oldA5;
-
- /* save various values required by ReadPacket/ReadRest */
- lap_hdr = (struct Lap802_header *) SetUpRDS(&rds);
- lap_hdr--;
- lap = (struct Lap802Info *)GetLAPPtr();
- oldA5 = (Ptr) A5Swap(lap->ipGlobals);
-
- rds.lap = (struct LAPInfo *)lap;
- rds.laphdr.length = sizeof(struct Lap802_header);
- rds.laphdr.ptr = (Ptr) lap_hdr;
-
- rds.lapBroadcast = (lap_hdr->lap_dest.lap_hi == 0xffff) && (lap_hdr->lap_dest.lap_lo == 0xffffffffL);
-
- /* process packet */
- if ((lap_hdr->lap_ls.lap_type == LAP_IP) && (lap->ip_ph != nil)) {
- /* give to IP packet receiver */
- lap->Lap802_stats.ip.pktin++;
- (*lap->ip_ph)(&rds);
- }
- else if (lap_hdr->lap_ls.lap_type == LAP_ARP) {
- /* give ARP packet to arp process */
- lap->Lap802_stats.arp.pktin++;
- Arp_read_ph(&rds);
- }
- else if (lap_hdr->lap_ls.lap_type == LAP_RARP) {
- /* give RARP packet to arp process */
- RARP_read_ph(&rds);
- }
- else {
- /* quietly discard unknown IEEE 802.3 packet types */
- lap->Lap802_stats.unknown++;
- ReadRest(&rds, nil, 0);
- }
- (void) A5Swap(oldA5);
- }
-
- /* Lap802_readE_ph is called by the Ethernet driver when a packet is received */
-
- void Lap802_readE_ph() /* read Ethernet packets */
- {
- struct rdStruct rds;
- struct Enet_header *en_hdr;
- struct Lap802Info *lap;
- Ptr oldA5;
-
- /* save various values required by ReadPacket/ReadRest */
- en_hdr = (struct Enet_header *) SetUpRDS(&rds);
- en_hdr--;
- lap = (struct Lap802Info *)GetLAPPtr();
- oldA5 = (Ptr) A5Swap(lap->ipGlobals);
-
- rds.lap = (struct LAPInfo *)lap;
- rds.laphdr.length = sizeof(struct Enet_header);
- rds.laphdr.ptr = (Ptr) en_hdr;
-
- rds.lapBroadcast = (en_hdr->en_dest.en_hi == 0xffff) && (en_hdr->en_dest.en_lo == 0xffffffffL);
-
- /* process packet */
- if ((en_hdr->en_type == LAP_IP) && (lap->ip_ph != nil)) {
- /* give to IP packet receiver */
- lap->Lap802_stats.ip.pktin++;
- (*lap->ip_ph)(&rds);
- }
- else if (en_hdr->en_type == LAP_ARP) {
- /* give ARP packet to arp process */
- lap->Lap802_stats.arp.pktin++;
- Arp_read_ph(&rds);
- }
- else if (en_hdr->en_type == LAP_RARP) {
- /* give RARP packet to arp process */
- RARP_read_ph(&rds);
- }
- else {
- /* quietly discard unknown Ethernet packet types */
- lap->Lap802_stats.unknown++;
- ReadRest(&rds, nil, 0);
- }
- (void) A5Swap(oldA5);
- }
-
- /* Lap802_writecomplete is called when IEEE 802.3 output is complete. It picks up A0
- (pointer to the ipb), sets up the global information (for IP) and then calls the
- higher-level ioc routine. */
-
- void Lap802_writecomplete()
- {
- struct ipbuf *ipb;
- Ptr oldA5;
-
- ipb = (struct ipbuf *) GetA0();
- oldA5 = (Ptr) A5Swap(((struct Lap802Info *)GetLAPPtr())->ipGlobals);
- ipb->iop.ioCompletion = ipb->ip_ioc;
- /* ipb->iop.ioNamePtr = (StringPtr) ipb->callerA5;*/
- IOComplete(ipb);
- (void) A5Swap(oldA5);
- }
-
- /* Lap802_write is called to initiate a transmission of the indicated
- IEEE 802.3 packet after translating the IP address to IEEE 802.3 address.
- This is the normal entry point for sending packets. */
-
- OSErr Lap802_write(lap, dest, ipb)
- struct Lap802Info *lap;
- ip_addr dest;
- struct ipbuf *ipb;
- {
- struct Lap802_header *lap_hdr;
- struct arp_info *arp;
- struct Lap802_addr *tka;
- struct ipbuf *arpipb, *next_ipb;
- short oldPS;
- OSErr rc;
-
- lap_hdr = (struct Lap802_header *)ipb->laphdr.ptr;
- if ((lap_hdr == nil) || (ipb->laphdr.length < sizeof(struct Lap802_header))) {
- /* WDS for the LAP wasn't set-up correctly */
- return(ipBadWDSErr);
- }
-
- ipb->laphdr.length = sizeof (struct Lap802_header);
-
- /* mark I/O as in progress */
- ipb->iop.ioResult = inProgress;
-
- /* save away caller's IOC address */
- ipb->ip_ioc = ipb->iop.ioCompletion;
- /* ipb->callerA5 = ipb->iop.ioNamePtr;*/
- ipb->iop.ioCompletion = (ProcPtr) Lap802_writecomplete;
-
- lap_hdr->lap_len = 0; /* calculate packet length in Lap802_writeit procedure */
- lap_hdr->lap_ls.lap_dsap = HEX_AA;
- lap_hdr->lap_ls.lap_ssap = HEX_AA;
- lap_hdr->lap_ls.lap_cntl = HEX_3;
- lap_hdr->lap_ls.lap_orghi = 0;
- lap_hdr->lap_ls.lap_orglo = 0;
- lap_hdr->lap_ls.lap_type = LAP_IP;
-
- oldPS = Disable();
- /* source address set by Ethernet driver. find destination address from ARP table */
- if (dest == lap->our_ip_addr || dest == lap->ip_broadcast_addr) {
- /* trying to send to ourselves. Since Ethernet is half-duplex,
- simulate the loopback */
- tka = &lap->our_lap_addr;
- lap_hdr->lap_dest = *tka;
- TLoopBack(&ipb->laphdr);
- if (dest == lap->ip_broadcast_addr) tka = IP_to_Lap802(lap, dest);
- }
- else
- tka = IP_to_Lap802(lap, dest);
-
- if (tka) {
- /* copy destination IEEE 802.3 address into packet and send */
- lap_hdr->lap_dest = *tka;
- rc = Lap802_writeit(lap, ipb);
- }
- else {
- /* IEEE 802.3 address not available, send an ARP. Overlay ARP control
- info on top of LAP header area */
- arpipb = (struct ipbuf *)lap->arp_q.qHead;
- while (arpipb) {
- next_ipb = (struct ipbuf *)arpipb->iop.qLink;
- if (((struct arp_info *)(arpipb->laphdr.ptr))->addr == dest) {
- /* just enque it and don't send out another ARP yet */
- arp = (struct arp_info *)ipb->laphdr.ptr;
- arp->timer = 3;
- arp->rtx = 0;
- arp->addr = dest;
- ipb->iop.qLink = 0;
- Enqueue((QElemPtr)ipb, &lap->arp_q);
- break;
- }
- /* look at next packet in queue */
- arpipb = (struct ipbuf *)next_ipb;
- }
- if (arpipb == nil) {
- arp = (struct arp_info *)ipb->laphdr.ptr;
- arp->timer = 3;
- arp->rtx = 0;
- arp->addr = dest;
- SendARP(lap, ARP_REQUEST, dest, &lap->lap_broadcast_addr);
- ipb->iop.qLink = 0;
- Enqueue((QElemPtr)ipb, &lap->arp_q);
- }
- rc = noErr;
- }
- Enable(oldPS);
- return(rc);
- }
-
- /* Lap802_Writeit is called to set up the IEEE 802.3 header and issue a write to the
- driver. Caller must have filled in the wds and ioCompletion address, if any. */
-
- OSErr Lap802_writeit(lap, ipb)
- struct Lap802Info *lap;
- struct ipbuf *ipb;
- {
- struct Lap802PB *tpb;
- struct wds *wdsp;
- struct Lap802_header *lap_hdr;
- struct wdsEntry *wds;
- unsigned short packetLen=0;
-
- lap_hdr = (struct Lap802_header *)ipb->laphdr.ptr;
- wds = (struct wdsEntry *) &ipb->ip;
- if (wds->length) packetLen += wds->length;
- wds = (struct wdsEntry *) &ipb->tp;
- if (wds->length) packetLen += wds->length;
- wds = (struct wdsEntry *) &ipb->data;
- if (wds->length) packetLen += wds->length;
- lap_hdr->lap_len = packetLen + sizeof(struct LLC_SNAP_header);
-
- tpb = (struct Lap802PB *)ipb;
- tpb->ioVRefNum = 0;
- tpb->ioRefNum = lap->link_unit;
- tpb->csCode = TWrite;
- wdsp = (struct wds *)&(ipb->laphdr.length);
- tpb->csParam.TWritePB.wdsPtr = wdsp;
- return(PBControl((ParmBlkPtr)tpb, true));
- }
-
- OSErr Lap802_control(lap)
- struct Lap802Info *lap;
- {
- #pragma unused (lap)
- return(unimpErr);
- }
-
- OSErr Lap802_statistics(tempLap, statsPtr)
- struct LAPInfo *tempLap;
- struct LAPStats *statsPtr;
- {
- struct Lap802Info *lap;
- #ifdef MPW3.0
- #pragma unused (lap)
- #endif
- lap = (struct Lap802Info *)tempLap;
- statsPtr->ifType = 1;
- statsPtr->ifMaxMTU = MAX_LAP802_PKT;
- statsPtr->ifSpeed = LAP802SPEED;
- statsPtr->ifPhyAddrLength = sizeof(struct Lap802_addr);
- statsPtr->ifPhysicalAddress = (char *)&lap->our_lap_addr;
- statsPtr->AddrXlation.arp_table = &lap->arp_table[0];
- return(noErr);
- }
-
- void config_RARP(lap)
- struct Lap802Info *lap;
- {
- int rtxCount;
- int rtxTime, rtxInterval;
- struct Lap802PB lappb;
- OSErr rc=-1;
- char prot_RARP[] = {HEX_1,HEX_AA,HEX_5,HEX_0,HEX_0,HEX_0,HEX_80,HEX_35,HEX_0};
-
- /* attach ethernet-RARP packet read handler to the ethernet driver */
- bzero((char *)&lappb, sizeof(lappb));
- lappb.ioRefNum = lap->link_unit;
- lappb.csCode = TAttachPH;
- lappb.csParam.TAttachPB.protocolType = LAP_RARP;
- lappb.csParam.TAttachPB.PHaddress = (ProcPtr) Lap802_readE_ph;
- if (PBControl((ParmBlkPtr)&lappb, false) != noErr)
- return;
-
- /* attach 802.3-RARP packet read handler to the LAP manager */
- rc = L802Attach((ProcPtr) Lap802p3_ph, (long) lap->link_unit, prot_RARP);
- if (rc != noErr)
- /* can't open RARP IEEE 802.3 type */
- return;
-
- rtxCount = 0;
- rtxInterval = 60;
-
- SendRARP(lap, RARP_REQUEST);
- rtxTime = TickCount() + rtxInterval;
- while (lap->our_ip_addr == 0) {
- if (TickCount() >= rtxTime) {
- /* time to retransmit reverse ARP */
- rtxCount++;
- rtxInterval += rtxInterval;
- if (rtxCount < MAX_ARP_COUNT) {
- SendRARP(lap, RARP_REQUEST);
- rtxTime = TickCount() + rtxInterval;
- }
- else
- break;
- }
- }
-
- /* release ethernet-RARP listner */
- lappb.csParam.TDetachPB.protocolType = LAP_RARP;
- PBControl((ParmBlkPtr)&lappb, false);
-
- /* release 802.3-RARP listener */
- rc = L802Detach((long) lap->link_unit, prot_RARP);
- }
-
- void SendRARP (lap,arp_code)
- struct Lap802Info *lap;
- int arp_code;
- {
- struct ipbuf *ipb;
- struct arp_header *arp_hdr;
- struct Lap802_header *lap_hdr;
- short oldPS;
-
- ipb = lap->arp_ipb;
- oldPS = Disable();
- if (ipb->iop.ioResult <= 0) {
- /* ipbuf available for sending RARPs */
-
- lap_hdr = (struct Lap802_header *)ipb->laphdr.ptr;
- lap_hdr->lap_dest = lap->lap_broadcast_addr;
- lap_hdr->lap_ls.lap_type = LAP_RARP;
-
- arp_hdr = (struct arp_header *)ipb->ip.ptr;
- arp_hdr->arp_opcode = arp_code;
- arp_hdr->arp_sha = lap->our_lap_addr;
- arp_hdr->arp_spa = 0;
- arp_hdr->arp_tha = lap->our_lap_addr;
- arp_hdr->arp_tpa = 0;
-
- Lap802_writeit(lap, ipb);
- }
- Enable(oldPS);
- }
-
- Boolean Lap802_probe(lap, addr)
- struct Lap802Info *lap;
- ip_addr addr;
- {
- int ticks;
-
- SendARP(lap, ARP_REQUEST, addr, &lap->lap_broadcast_addr);
-
- /* wait around a few milliseconds to see if anyone responds */
- ticks = TickCount() + 5;
- while ((TickCount() <= ticks) && (lap->addressConflict == false))
- /* wait around */
- ;
- return(!lap->addressConflict);
- }
-
- Boolean Lap802_register(lap)
- struct Lap802Info *lap;
- {
- /* verify that no-one else is using our address, best we can do on the
- Ethernet */
- lap->addressConflict = false;
- return(Lap802_probe(lap, lap->our_ip_addr));
- }
-
- /* Lap802_close is called to close the Ethernet driver */
-
- OSErr Lap802_close(lap)
- struct Lap802Info *lap;
- {
- OSErr rc = -1;
- struct Lap802PB lappb;
- char prot_IP[] = {HEX_1,HEX_AA,HEX_5,HEX_0,HEX_0,HEX_0,HEX_8,HEX_0,HEX_0};
- char prot_ARP[] = {HEX_1,HEX_AA,HEX_5,HEX_0,HEX_0,HEX_0,HEX_8,HEX_6,HEX_0};
-
- /* kill any pending VRT tasks or ARP requests */
- Arp_close(lap);
-
- /* release ethernet-IP listner */
- bzero((char *)&lappb, sizeof(lappb));
- lappb.ioRefNum = lap->link_unit;
- lappb.csCode = TDetachPH;
- lappb.csParam.TDetachPB.protocolType = LAP_IP;
- PBControl((ParmBlkPtr)&lappb, false);
-
- /* release ethernet-ARP listner */
- lappb.csParam.TDetachPB.protocolType = LAP_ARP;
- PBControl((ParmBlkPtr)&lappb, false);
-
- /* release 802.3-IP listner */
- rc = L802Detach((long) lap->link_unit, prot_IP);
-
- /* release 802.3-ARP listner */
- rc = L802Detach((long) lap->link_unit, prot_ARP);
-
- return(noErr);
- }
-